#include "VStdAfx.h"
#include "KRUtilityD3D9.h"



const char* FormatD3DError(HRESULT h)
{
#define D3DERR(x) case x: return TEXT(#x);
	switch( h )
	{
		D3DERR(D3D_OK)
			D3DERR(D3DERR_WRONGTEXTUREFORMAT)
			D3DERR(D3DERR_UNSUPPORTEDCOLOROPERATION)
			D3DERR(D3DERR_UNSUPPORTEDCOLORARG)
			D3DERR(D3DERR_UNSUPPORTEDALPHAOPERATION)
			D3DERR(D3DERR_UNSUPPORTEDALPHAARG)
			D3DERR(D3DERR_TOOMANYOPERATIONS)
			D3DERR(D3DERR_CONFLICTINGTEXTUREFILTER)
			D3DERR(D3DERR_UNSUPPORTEDFACTORVALUE)
			D3DERR(D3DERR_CONFLICTINGRENDERSTATE)
			D3DERR(D3DERR_UNSUPPORTEDTEXTUREFILTER)
			D3DERR(D3DERR_CONFLICTINGTEXTUREPALETTE)
			D3DERR(D3DERR_DRIVERINTERNALERROR)
			D3DERR(D3DERR_NOTFOUND)
			D3DERR(D3DERR_MOREDATA)
			D3DERR(D3DERR_DEVICELOST)
			D3DERR(D3DERR_DEVICENOTRESET)
			D3DERR(D3DERR_NOTAVAILABLE)
			D3DERR(D3DERR_OUTOFVIDEOMEMORY)
			D3DERR(D3DERR_INVALIDDEVICE)
			D3DERR(D3DERR_INVALIDCALL)
			D3DERR(D3DERR_DRIVERINVALIDCALL)
			D3DERR(D3DXERR_INVALIDDATA)
			D3DERR(E_OUTOFMEMORY)
	default: 
		return "Unknwon D3D Error.";
	}
#undef D3DERR

}
const char* GetD3DFormatString(D3DFORMAT Format)
{
	switch(Format) 
	{
	case D3DFMT_R8G8B8:
		return "D3DFMT_R8G8B8";
	case D3DFMT_A8R8G8B8:
		return "D3DFMT_A8RBG8B8";
	default:
		return "D3DFMT_UNKNOWN";
	}
}

D3DDECLTYPE		D3D9Translator::VenusToD3DVertDeclType[VRVET_MAX];
D3DDECLUSAGE	D3D9Translator::VenusToD3DVertDeclUsage[VRVEU_MAX];
D3DCMPFUNC		D3D9Translator::VenusToD3DCompare[VRCF_MAX];
D3DFILLMODE		D3D9Translator::VenusToD3DFillMode[VRRFM_MAX];
D3DCULL			D3D9Translator::VenusToD3DCull[VRRCM_MAX];
D3DTEXTUREADDRESS D3D9Translator::VenusToD3DAddress[VRSAM_MAX];
D3DBLENDOP		D3D9Translator::VenusToD3DBlendOp[VRBO_MAX];
D3DBLEND		D3D9Translator::VenusToD3DBlend[VRBF_MAX];
D3DSTENCILOP D3D9Translator::VenusToD3DStencilOp[VRSO_MAX];
D3DPRIMITIVETYPE		D3D9Translator::VenusToD3DPrimitiveType[VRPT_MAX];

D3DDECLTYPE D3D9Translator::ToD3D(EVRVertexElementType VType)
{
	switch(VType) 
	{
	case VRVET_FLOAT4: 
		return D3DDECLTYPE_FLOAT4;
	case VRVET_FLOAT3:
		return D3DDECLTYPE_FLOAT3;
	case VRVET_FLOAT2:
		return D3DDECLTYPE_FLOAT2;
	case VRVET_FLOAT1:
		return D3DDECLTYPE_FLOAT1;
	//case VRVET_DWORD:
	//	return D3DDECLTYPE_D3DCOLOR;
	case VRVET_UBYTE4N:
		return D3DDECLTYPE_UBYTE4N;
	case VRVET_SHORT2:
		return D3DDECLTYPE_SHORT2;
	case VRVET_UBYTE4:
		return D3DDECLTYPE_UBYTE4;
	}
	//D3DLOG("Error Enum Value\n");
	return (D3DDECLTYPE)-1;
}

D3DDECLUSAGE D3D9Translator::ToD3D(EVRVertexElementUsage VUsage)
{
	//Index = 0;
	switch(VUsage) 
	{
	case VRVEU_POSITION:
		return D3DDECLUSAGE_POSITION;
	case VRVEU_NORMAL:
		return D3DDECLUSAGE_NORMAL;
	case VRVEU_COLOR:
		return D3DDECLUSAGE_COLOR;
	case VRVEU_TANGENT:
		return D3DDECLUSAGE_TANGENT;
	case VRVEU_BINORMAL:
		return D3DDECLUSAGE_BINORMAL;
	case VRVEU_TEXCOORD:
		return D3DDECLUSAGE_TEXCOORD;
	case VRVEU_BLEND_INDICES:
		return D3DDECLUSAGE_BLENDINDICES;
	case VRVEU_BLEND_WEIGHT:
		return D3DDECLUSAGE_BLENDWEIGHT;
	}
	//D3DLOG("Error Enum Value\n");
	return (D3DDECLUSAGE)-1;
}

D3DCMPFUNC D3D9Translator::ToD3D(EVRCompareFunc CompFunc)
{
	switch(CompFunc) 
	{
	case VRCF_NEVER : return D3DCMP_NEVER;
	case VRCF_LESS: return D3DCMP_LESS;
	case VRCF_EQUAL: return D3DCMP_EQUAL;
	case VRCF_LESSEQUAL: return D3DCMP_LESSEQUAL;
	case VRCF_GREATER: return D3DCMP_GREATER;
	case VRCF_NOTEQUAL: return D3DCMP_NOTEQUAL;
	case VRCF_GREATEREQUAL: return D3DCMP_GREATEREQUAL;
	case VRCF_ALWAYS: return D3DCMP_ALWAYS;
	default:
		return D3DCMP_NEVER;
	}
}

D3DFILLMODE D3D9Translator::ToD3D(EVRRasterizerFillMode FillMode)
{
	switch(FillMode) 
	{
	case VRRFM_POINT: return D3DFILL_POINT;
	case VRRFM_WIREFRAME: return D3DFILL_WIREFRAME;
	case VRRFM_SOLID: return D3DFILL_SOLID;
	default:
		return D3DFILL_SOLID;
	}
}

D3DCULL D3D9Translator::ToD3D(EVRRasterizerCullMode CullMode)
{
	switch(CullMode) 
	{
	case VRRCM_CW: return D3DCULL_CW;
	case VRRCM_CCW: return D3DCULL_CCW;
	case VRRCM_NONE: return D3DCULL_NONE;
	default: return D3DCULL_NONE;
	}
}


D3DTEXTUREADDRESS D3D9Translator::ToD3D(EVRSamplerAddressMode AddressMode)
{
	switch(AddressMode) 
	{
	case VRSAM_WRAP: return D3DTADDRESS_WRAP;
	case VRSAM_CLAMP: return D3DTADDRESS_CLAMP;
	case VRSAM_MIRROR: return D3DTADDRESS_MIRROR;
	default: return D3DTADDRESS_BORDER;
	}
}

D3DBLENDOP D3D9Translator::ToD3D(EVRBlendOp BlendOp)
{
	switch(BlendOp)
	{
	case VRBO_SUBTRACT: return D3DBLENDOP_SUBTRACT;
	case VRBO_Min: return D3DBLENDOP_MIN;
	case VRBO_Max: return D3DBLENDOP_MAX;
	case VRBO_REVERSESUBTRACT: return D3DBLENDOP_REVSUBTRACT;
	default: return D3DBLENDOP_ADD;
	};
}

D3DBLEND D3D9Translator::ToD3D(EVRBlendFactor BlendFactor)
{
	switch(BlendFactor)
	{
	case VRBF_ONE: return D3DBLEND_ONE;
	case VRBF_SRC_COLOR: return D3DBLEND_SRCCOLOR;
	case VRBF_INV_SRC_COLOR: return D3DBLEND_INVSRCCOLOR;
	case VRBF_DEST_COLOR: return D3DBLEND_DESTCOLOR;
	case VRBF_INV_DEST_COLOR: return D3DBLEND_INVDESTCOLOR;
	case VRBF_SRC_ALPHA: return D3DBLEND_SRCALPHA;
	case VRBF_INV_SRC_ALPHA: return D3DBLEND_INVSRCALPHA;
	case VRBF_DEST_ALPHA: return D3DBLEND_DESTALPHA;
	case VRBF_INV_DEST_ALPHA: return D3DBLEND_INVDESTALPHA;
	case VRBF_CONSTANTBLENDCOLOR: return D3DBLEND_BLENDFACTOR;
	default: return D3DBLEND_ZERO;
	};
}

D3DSTENCILOP D3D9Translator::ToD3DStencilOp(EVRStencilOp vStencilOp)
{
	switch(vStencilOp)
	{
	case VRSO_KEEP: return D3DSTENCILOP_KEEP;
	case VRSO_ZERO: return D3DSTENCILOP_ZERO;
	case VRSO_REPLACE: return D3DSTENCILOP_REPLACE;
	case VRSO_INCSAT: return D3DSTENCILOP_INCRSAT;
	case VRSO_DECSAT: return D3DSTENCILOP_DECRSAT;
	case VRSO_INVERT: return D3DSTENCILOP_INVERT;
	case VRSO_INC: return D3DSTENCILOP_INCR;
	case VRSO_DEC: return D3DSTENCILOP_DECR;
	default:
		return D3DSTENCILOP_KEEP;
	}
}

D3DPRIMITIVETYPE D3D9Translator::ToD3DPrimitiveType(EVRPrimitiveType vPrimitiveType)
{
	switch(vPrimitiveType)
	{
	case VRPT_TRIANGLELIST: return D3DPT_TRIANGLELIST;
	case VRPT_TRIANGLESTRIP: return D3DPT_TRIANGLESTRIP;
	case VRPT_LINELIST: return D3DPT_LINELIST;
	case VRPT_LINESTRIP: return D3DPT_LINESTRIP;
	case VRPT_POINTSPRITE: return D3DPT_POINTLIST;
	case VRPT_CONTROL_POINT: return D3DPT_POINTLIST;
	default: return D3DPT_POINTLIST;
	}
}



void D3D9Translator::Init()
{
	static BOOL bInit = FALSE;
	if (bInit)
	{
		return;
	}
	int i;
	for (i = 0; i < VRVET_MAX; i++)
	{
		VenusToD3DVertDeclType[i] = ToD3D((EVRVertexElementType)i);
	}

	for (i = 0; i < VRVEU_MAX; i++)
	{
		VenusToD3DVertDeclUsage[i] = ToD3D((EVRVertexElementUsage)i);
	}
	for (i = 0; i < VRCF_MAX; i++)
	{
		VenusToD3DCompare[i] = ToD3D((EVRCompareFunc)i);
	}
	for (i = 0; i < VRRFM_MAX; i++)
	{
		VenusToD3DFillMode[i] = ToD3D((EVRRasterizerFillMode)i);
	}
	for (i = 0; i < VRRCM_MAX; i++)
	{
		VenusToD3DCull[i] = ToD3D((EVRRasterizerCullMode)i);
	}
	for (i = 0; i < VRSAM_MAX; i++)
	{
		VenusToD3DAddress[i] = ToD3D((EVRSamplerAddressMode)i);
	}
	for (i = 0; i < VRBO_MAX; i++)
	{
		VenusToD3DBlendOp[i] = ToD3D((EVRBlendOp)i);
	}
	for (i = 0; i < VRBF_MAX; i++)
	{
		VenusToD3DBlend[i] = ToD3D((EVRBlendFactor)i);
	}
	for (i = 0; i < VRSO_MAX; i++)
	{
		VenusToD3DStencilOp[i] = ToD3DStencilOp((EVRStencilOp)i);
	}
	for (i = 0; i < VRPT_MAX; i++)
	{
		VenusToD3DPrimitiveType[i] = ToD3DPrimitiveType((EVRPrimitiveType)i);
	}

	bInit = TRUE;
}


void D3D9Translator::InitPixelFormats()
{
	for (UINT VenusFormat = 1; VenusFormat < VRPF_MAX; ++VenusFormat)
	{
		UINT& RenderFormat = _v_PixelFormatDesc[VenusFormat].RenderFormat;
		RenderFormat = 0;

		switch(VenusFormat)
		{
		case VRPF_R8: RenderFormat = D3DFMT_L8; break;
		case VRPF_RG8: RenderFormat = D3DFMT_A8L8; break;
		case VRPF_RGB8: RenderFormat = D3DFMT_X8R8G8B8; break;
		case VRPF_RGBA8:RenderFormat = D3DFMT_A8R8G8B8; break;
		case VRPF_R16:	RenderFormat = D3DFMT_L16; break;
		case VRPF_RG16:RenderFormat = D3DFMT_G16R16; break;
		case VRPF_RGB16:RenderFormat = D3DFMT_UNKNOWN; break;		// RGB16 not directly supported
		case VRPF_RGBA16:RenderFormat = D3DFMT_A16B16G16R16; break;
		
		case VRPF_R16F:	RenderFormat = D3DFMT_R16F; break;
		case VRPF_RG16F:RenderFormat = D3DFMT_G16R16F; break;
		case VRPF_RGB16F:RenderFormat = D3DFMT_UNKNOWN; break;		// RGB16F not directly supported
		case VRPF_RGBA16F:RenderFormat = D3DFMT_A16B16G16R16F; break;

		case VRPF_R32F:	RenderFormat = D3DFMT_R32F; break;
		case VRPF_RG32F:RenderFormat = D3DFMT_G32R32F; break;
		case VRPF_RGB32F:RenderFormat = D3DFMT_UNKNOWN; break;		// RGB16 not directly supported
		case VRPF_RGBA32F:RenderFormat = D3DFMT_A32B32G32R32F; break;

		case VRPF_RGB565:	RenderFormat = D3DFMT_R5G6B5; break;
		case VRPF_RGBA4:RenderFormat = D3DFMT_A4R4G4B4; break;
		case VRPF_RGB5A1:RenderFormat = D3DFMT_A1R5G5B5; break;		
		case VRPF_RGB10A2:RenderFormat = VRPF_RGB10A2; break;

		case VRPF_DXT1:	RenderFormat = D3DFMT_DXT1; break;
		case VRPF_DXT3:RenderFormat = D3DFMT_DXT3; break;
		case VRPF_DXT5:RenderFormat = D3DFMT_DXT5; break;		
		case VRPF_ATI1:RenderFormat = MAKEFOURCC('A','T','I','1'); break;
		case VRPF_ATI2:RenderFormat = MAKEFOURCC('A','T','I','2'); break;		
		case VRPF_ETC1:RenderFormat = D3DFMT_UNKNOWN; break;

		case VRPF_D16:
			{
				RenderFormat = D3DFMT_D16;
				break;
			}
		case VRPF_D24:
			{
				RenderFormat = D3DFMT_D24X8; 
				break;
			}
		case VRPF_D24S8:
			{
				RenderFormat = D3DFMT_D24S8; 
				break;
			}
		case VRPF_D32F:
			{
				RenderFormat = D3DFMT_D32; 
				break;
			}
		case VRPF_D32FS8:
			{
				RenderFormat = D3DFMT_UNKNOWN; 
				break;
			}
		case VRPF_DS_AUTO:
			{
				RenderFormat = D3DFMT_D24S8; 
				break;
			}
		case VRPF_DEPTHSHADOW:
			{
				RenderFormat = D3DFMT_D24S8; 
				break;
			}
		case VRPF_FOURCC_NULL:
			{
				RenderFormat = MAKEFOURCC('N','U','L','L'); 
				break;
			}
		default:
			RenderFormat = D3DFMT_UNKNOWN;
			break;
		}
	}
}

void D3DVerify(HRESULT D3DResult,const char* Code, const char* Filename,UINT Line)
{
	if(FAILED(D3DResult))
	{
		const char* Error = FormatD3DError(D3DResult);
//		D3DLOG("%s failed at %s:%u with error %s",Code,Filename,Line,Error);
	}
}
